#if ANDROID
using InteractiveMusicPlayerMobile.安卓平台.辅助类;
#endif
using InteractiveMusicPlayerMobile.控件与界面;
using InteractiveMusicPlayerMobile.辅助类;
using NAudio.Wave;
using PropertyChanged;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using 交互音乐播放器.中间件;
using 交互音乐播放器.数据;
using 交互音乐播放器.数据.播放中数据;
using static 交互音乐播放器.数据.元数据获取;

namespace InteractiveMusicPlayerMobile;
[AddINotifyPropertyChangedInterface]
public partial class 文件浏览器 : ContentPage, INotifyPropertyChanged
{

    public ObservableCollection<文件与文件夹> 显示集 { get; set; } = new ObservableCollection<文件与文件夹>();
    public Dictionary<string, 文件与文件夹> 显示项 { get; set; } = new Dictionary<string, 文件与文件夹>();
    public 播放信息 播放信息 { get; set; } = new 播放信息();
    public static 文件浏览器 运行时 { get; set; }
    public 文件与文件夹 当前播放文件 { get; set; }
    public string 启动目录 { get; set; }
    public static object 目录刷新锁 { get; set; } = new object();
    public bool 正在更新目录 = false;
    private string _当前浏览路径;
    public string 当前浏览路径
    {
        get { return _当前浏览路径; }
        set { _当前浏览路径 = value; OnPropertyChanged(nameof(当前浏览路径)); }
    }
    public List<string> 浏览历史 { get; set; } = new List<string>(5);
    public int 浏览历史指针 { get; set; }
    public int 浏览历史最大记录数 { get; set; } = 10;
    [AddINotifyPropertyChangedInterface]
    public class 文件与文件夹 : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public enum 显示类型
        {
            文件,
            文件夹
        }
        public string 显示图标 { get; set; }
        public 显示类型 Type { get; set; }
        public string 文件组名 { get; set; }
        public List<string> 绝对路径 { get; set; } = new List<string>();
        public List<string> 子文件标记 { get; set; } = new List<string>();
        public List<MemoryStream> 内存音频文件 { get; set; } = new List<MemoryStream>();
        public string 文件类型 { get; set; }
        public 脚本文件数据 脚本文件 { get; set; }
        public Dictionary<文件名称信息, string> 元数据 { get; set; }
    }


    public 文件浏览器()
    {
        InitializeComponent();
        BindingContext = this;
        运行时 = this;
        程序启动();
    }

    private void 程序启动()
    {
        this.Loaded += 加载完毕;
        通知与日志.当前页 = this;
    }

    private async void 加载完毕(object sender, EventArgs e)
    {
        if (!File.Exists(辅助类.文件.获取程序数据路径() + "已授权.配置"))
        {
            var 用户回执 = await 权限.检查并授予权限(this);
            if (用户回执)
            {
                辅助类.权限.检查并授予所有文件管理权();
                File.Create(辅助类.文件.获取程序数据路径() + "已授权.配置");
            }
        }


        var 默认路径 = 文件.获取默认存储路径();
        Task.Run(() => { 打开目录(默认路径); });

        文件与文件夹列表.Focus();
        启动目录 = 辅助类.文件.获取默认存储路径();
    }

    /// <summary>
    /// 在文件管理器中打开某个目录
    /// </summary>
    /// <param name="目录绝对路径">打开的目录</param>
    /// <param name="不压入历史栈">是否要压入历史记录堆栈</param>
    public async void 打开目录(string 目录绝对路径, bool 不压入历史栈 = false)
    {
        if (正在更新目录) { return; }
        正在更新目录 = true;
        #region 判空并初始列表
        if (目录绝对路径 == null) { return; }
        if (!Directory.Exists(目录绝对路径))
        {
            DisplayAlert("不可读取的路径", $"无法打开该路径，可能是因为权限不足\r\n{目录绝对路径}", "关闭");
            return;
        }
        显示集.Clear();
        显示项.Clear();
        var 文件夹列表 = Directory.GetDirectories(目录绝对路径);
        #endregion
        #region 处理文件夹
        foreach (var 文件夹 in 文件夹列表)
        {
            if (文件夹.Contains('.')) { continue; }
            var 显示项 = new 文件与文件夹();
            显示项.文件组名 = Path.GetFileName(文件夹);
            显示项.绝对路径 = new() { 文件夹 };
            显示项.Type = 文件与文件夹.显示类型.文件夹;
            显示项.显示图标 = "\ue647";
            Application.Current.Dispatcher.Dispatch(() =>
            {
                显示集.Add(显示项);
            });

        }
        #endregion
        #region 处理文件到临时集合
        var 文件列表 = Directory.GetFiles(目录绝对路径, "*.ogg");
        foreach (var 文件绝对路径 in 文件列表) //遍历每个文件并处理操作
        {
            var 显示项 = new 文件与文件夹();
            var 文件名元数据 = 元数据获取.识别文件名信息(文件绝对路径);
            var 文件组名称集 = Path.GetFileNameWithoutExtension(文件绝对路径).Split('_');
            if (文件组名称集.Length < 2)//非文件组的逻辑（组内只有一个文件）
            {
                显示项.文件组名 = 文件组名称集.FirstOrDefault();
                显示项.Type = 文件与文件夹.显示类型.文件;
                显示项.文件类型 = Path.GetExtension(文件绝对路径);
                显示项.显示图标 = "\ue699";
                显示项.绝对路径 = new() { 文件绝对路径 };
                显示项.子文件标记 = new List<string>() { "默认循环" };
                显示项.元数据 = 文件名元数据;
                this.显示项.TryAdd(显示项.文件组名, 显示项);
            }
            else //文件组的逻辑（组内包含多个文件）
            {
                显示项.文件组名 = 文件组名称集.FirstOrDefault();
                if (!this.显示项.TryAdd(显示项.文件组名, 显示项)) //如果添加未成功，说明信息已被创建，只需添加绝对路径
                {
                    this.显示项[显示项.文件组名].绝对路径.Add(文件绝对路径);
                    this.显示项[显示项.文件组名].子文件标记.Add(文件组名称集[1]);
                }
                else //如果添加成功，说明信息已被创建，并且已通过刚才的操作传入字典，要新设置信息
                {
                    显示项.绝对路径.Add(文件绝对路径);
                    显示项.子文件标记.Add(文件组名称集[1]);
                    显示项.Type = 文件与文件夹.显示类型.文件;
                    显示项.文件类型 = Path.GetExtension(文件绝对路径);
                    显示项.元数据 = 文件名元数据;
                    显示项.显示图标 = "\ue682";
                }

            }
        }
        #endregion
        //子线程提升速度
        await Task.Run(() =>
        {
        #region 处理文件到显示集合
            var 文件集 = 显示项.Values.ToList().FindAll(x => x.Type == 文件与文件夹.显示类型.文件);
            foreach (var 文件 in 显示项.Values) { 显示集.Add(文件); }

            #endregion
        #region 识别并处理脚本文件
            文件集.ForEach((x) => { x.脚本文件 = 交互音乐播放器.数据.脚本文件读写器.获取并设置脚本文件(x); });
            #endregion
            Thread.Sleep(100);
            正在更新目录 = false;
        });

        #region 历史记录处理
        if (当前浏览路径 == 目录绝对路径)
        {
           
            return;
        }
        if (!不压入历史栈)
        {
            当前浏览路径 = 目录绝对路径;
            记录历史(目录绝对路径);
        }
        /* 解除注释可查看浏览记录堆栈
        foreach (var 历史 in 浏览历史)
        {
            if (历史 == 浏览历史[浏览历史指针])
            {
                Debug.WriteLine($"> {历史}");
            }
            else { Debug.WriteLine($"- {历史}"); }

        }
        */
        当前浏览路径 = 目录绝对路径;
        #endregion

    }

    public void 滚动到项(文件与文件夹 显示项)
    {
        文件与文件夹列表.ScrollTo(显示项, ScrollToPosition.Start, true);
    }

    private void 记录历史(string 当前目录)
    {
        //删除前面的


        if (浏览历史指针 < 浏览历史.Count - 1)
        {

            浏览历史.RemoveRange(浏览历史指针 + 1, 浏览历史.Count - 1 - 浏览历史指针);
        }
        //超过的清空
        if (浏览历史指针 + 1 > 浏览历史最大记录数)
        {

            浏览历史.RemoveAt(0);
        }
        浏览历史.Add(当前目录);
        浏览历史指针 = 浏览历史.Count - 1;


    }
    public enum 翻阅状态 { 前, 后 };

    public string 翻阅历史(翻阅状态 状态)
    {
        if (浏览历史.Count == 0) { Debug.WriteLine("没有记录的历史"); return null; }
        if (状态 == 翻阅状态.前)
        {
            if (浏览历史指针 <= 0) { Debug.WriteLine("已经是最前面的历史记录了"); return 浏览历史[0]; }
            浏览历史指针--;
            return 浏览历史[浏览历史指针];
        }
        if (状态 == 翻阅状态.后)
        {
            if (浏览历史指针 >= 浏览历史.Count - 1) { Debug.WriteLine("已经是最后面的历史记录了"); return 浏览历史[浏览历史.Count - 1]; }
            浏览历史指针++;
            return 浏览历史[浏览历史指针];
        }
        Debug.WriteLine("出现错误");
        return null;
    }

    private void 打开文件夹或播放文件(文件与文件夹 已选择项)
    {
        Debug.WriteLine(已选择项.绝对路径);
        if (已选择项.Type == 文件与文件夹.显示类型.文件夹)
        {
            try { 打开目录(已选择项.绝对路径.FirstOrDefault()); }
            catch (Exception ex) { DisplayAlert("不可读取的路径", $"无法打开该路径，可能是因为权限不足，已返回默认路径。\r\n路径名：{Path.GetDirectoryName(当前浏览路径)}\r\n内部信息：{ex.Message}", "关闭"); 打开目录(启动目录); }

        }
        else
        {
            播放信息.运行时.媒体信息 = 已选择项;
            播放文件(已选择项);
        }
    }



    private void 播放文件(文件与文件夹 文件信息)
    {
        //var 文件组信息 = 音频解析.解析Ogg文件(文件信息.绝对路径, 文件信息);

        播放信息.音频名称 = Path.GetFileNameWithoutExtension(文件信息.文件组名);

        交互音乐播放器.中间件.音频控制中间件 中间件 = new 音频控制中间件(文件信息.脚本文件);
#if ANDROID
InteractiveMusicPlayerMobile.音频播放.安卓音频播放.启动播放服务();
#endif

        播放按钮.Text = "\ue6a9";
    }

    public void 播放与暂停()
    {
        if (音频控制中间件.当前中间件 == null) { return; }
        if (音频控制中间件.当前音频控制器 == null) { return; }
       if (音频控制中间件.播放数据.当前流.当前段落.状态 == 段落信息.播放状态.播放中)
        {
            音频控制中间件.当前中间件.命令_暂停();
            播放按钮.Text = "\ue6a8";
        }
       else
        {
            音频控制中间件.当前中间件.命令_继续所有();
            播放按钮.Text = "\ue6a9";
        }
        return;
        /*
#if ANDROID
        if (安卓平台.辅助类.音频播放.运行时 == null) { Debug.WriteLine("找不到运行的实例，无法播放与暂停"); return; }
        if (安卓平台.辅助类.音频播放.运行时.播放)
        {
            Debug.WriteLine("正在暂停");
            安卓平台.辅助类.音频播放.运行时.暂停();
            播放按钮.Text = "\ue6a8";
        }
        else
        {
            Debug.WriteLine("正在播放");
            安卓平台.辅助类.音频播放.运行时.恢复播放();
            播放按钮.Text = "\ue6a9";
        }
#endif
        */

    }

    private void 设置进度(double 进度)
    {
        if (音频控制中间件.当前中间件 == null) { return; }
        if (音频控制中间件.当前音频控制器 == null) { return; }
        if (音频控制中间件.播放数据.当前流.当前段落.状态 == 段落信息.播放状态.播放中)
        {
            音频控制中间件.当前中间件.命令_全部重定位((float)进度);
        }
        return;
        /*
#if ANDROID

        if (安卓平台.辅助类.音频播放.运行时 != null)
        { 安卓平台.辅助类.音频播放.运行时.设置进度(进度); }
        

#endif
        */
    }


    private void 打开文件夹_Clicked(object sender, EventArgs e)
    {
        Task.Run(() => { 打开目录(启动目录); });

    }

    private void 刷新_Clicked(object sender, EventArgs e)
    {
        打开目录(当前浏览路径);
    }

    private void 文件与文件夹列表_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        var 列表 = (ListView)sender;
        var 已选择项 = (文件与文件夹)列表.SelectedItem;

        打开文件夹或播放文件(已选择项);
    }


    private void 播放按钮_Clicked(object sender, EventArgs e)
    {
        播放与暂停();
    }


    private void 后退_Clicked(object sender, EventArgs e)
    {
        打开目录(翻阅历史(翻阅状态.前), true);
    }

    private void 前进_Clicked(object sender, EventArgs e)
    {
        打开目录(翻阅历史(翻阅状态.后), true);
    }



    private void 返回上级文件夹_Clicked(object sender, EventArgs e)
    {
        try { 打开目录(Path.GetDirectoryName(当前浏览路径)); }
        catch (Exception ex) { DisplayAlert("不可读取的路径", $"无法打开该路径，可能是因为权限不足，已返回默认路径。\r\n路径名：{Path.GetDirectoryName(当前浏览路径)}\r\n内部信息：{ex.Message}", "关闭"); 打开目录(启动目录); }

    }

    public event PropertyChangedEventHandler? PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


    private void Slider_DragCompleted(object sender, EventArgs e)
    {
        var 进度条 = (Slider)sender;
        设置进度(进度条.Value);
        播放信息.拖动中 = false;
    }

    private void Slider_DragStarted(object sender, EventArgs e)
    {
        播放信息.拖动中 = true;
    }



    private async void 曲目选项_Clicked_1(object sender, EventArgs e)
    {
        string 用户回执 = await DisplayActionSheet("要如何处理该文件", "取消", null, "播放", "编辑配置与脚本");
        var 控件 = (Button)sender;
        var 父控件 = (ContentView)控件.Parent.Parent;
        var 选中项 = (文件与文件夹)父控件.BindingContext;
        Debug.WriteLine(选中项.文件组名);
        if (用户回执 == "播放") { 打开文件夹或播放文件(选中项); }
        if (用户回执 == "编辑配置与脚本")
        {
            var 脚本编辑页 = new 脚本编辑();
            脚本编辑页.载入文件(选中项.脚本文件);
            脚本编辑页.BindingContext = 选中项;
            await Navigation.PushModalAsync(脚本编辑页);
        }


    }
    //重写返回按钮
    protected override bool OnBackButtonPressed()
    {
        if (浏览历史指针 == 0) { return false; }
        打开目录(翻阅历史(翻阅状态.前),true);
        return true;
    }

    private void 交互按键_Clicked(object sender, EventArgs e)
    {
        Debug.WriteLine("执行交互");
        if (音频控制中间件.播放数据 == null || 音频控制中间件.播放数据.空值或空引用(音乐播放数据.播放数据组.当前段落)
    || 计划.全局事件 == null || 脚本解析器.当前解析 == null)
        {
            return;
        }
        计划.全局事件.Add(计划.事件.按下默认按钮);
        UI界面数据.默认按钮名称 = "处理...";
        UI界面数据.默认按钮状态 = false;
    }
}